package grammar;

import geometry.GeomMatch;
import geometry.GeomMatcher;
import geometry.Geometry;
import graph.GNode;
import graph.GraphMatch;
import graph.GraphMatcher;

import java.util.ArrayList;
import java.util.List;

public class Matcher {
    public static List<Match> findRuleMatches(Design design, Rule rule) {       
        
        //find the graph matches
        List<GraphMatch> graphMatches = GraphMatcher.findGraphMatches(rule.getLHS(), design); 

        List<Match> incompleteMatches = new ArrayList<Match>();
        List<Match> completeMatches = new ArrayList<Match>();

        for (GraphMatch graphMatch : graphMatches) {
            incompleteMatches.add(new Match(rule, graphMatch));
        }

        while (!incompleteMatches.isEmpty()) {
            Match match = incompleteMatches.get(0);
            incompleteMatches.remove(0);
            if (match.isComplete(rule.getLHS().getNodeCount())) {
                completeMatches.add(match);
                continue;
            }
            
            GNode lhsNode = match.getNextNodeforGeometricMatch();
            GNode designNode = match.getMatchedNode(lhsNode); //we are checking for valid matches between the geometries mapped to lhsnode and the designnode
            Geometry designGeometry = (Geometry) designNode; 
            Geometry lhsGeometry = (Geometry) lhsNode;
            
            //we need to try to match each lhsGeometry to each designGeometry, then check the transformation on other design geometries
            List<GeomMatch> geomMatches = GeomMatcher.findGeomMatches(lhsGeometry, designGeometry);

            //if geometric matches were made - update lists
            if (!geomMatches.isEmpty()) {
                for (GeomMatch geomMatch : geomMatches) {
                    Match matchCopy = match.copy();
                    matchCopy.addGeomMatch(lhsNode, geomMatch);
                    incompleteMatches.add(matchCopy);
                }
            }
        }
        
        checkConstraints(design, rule, completeMatches);
        
        return completeMatches;
    }

    private static void checkConstraints(Design design, Rule rule, List<Match> matches) {
        //TODO
        //check each match to ensure that all constraints are satisfied
    }
}
